// ! 虚无的 never 类型
// 此前我们已经了解了另一个“什么都没有”的类型，void。但相比于 void ，never 还要更加空白一些。

type UnionWithNever = "linbudu" | 599 | true | void | never;
//将鼠标悬浮在类型别名之上，你会发现这里显示的类型是"linbudu" | 599 | true | void。never 类型被直接无视掉了，而 void 仍然存在。这是因为，void 作为类型表示一个空类型，就像没有返回值的函数使用 void 来作为返回值类型标注一样，void 类型就像 JavaScript 中的 null 一样代表“这里有类型，但是个空类型”。

//而 never 才是一个“什么都没有”的类型，它甚至不包括空的类型，严格来说，never 类型不携带任何的类型信息，因此会在联合类型中被直接移除，比如我们看 void 和 never 的类型兼容性：

declare let v1: never;
declare let v2: void;
declare let v3: string;
// v1 = v2; // X 类型 void 不能赋值给类型 never

// v2 = v1;

// v3 = v1

// 在编程语言的类型系统中，never 类型被称为 Bottom Type，是整个类型系统层级中最底层的类型。和 null、undefined 一样，它是所有类型的子类型，但只有 never 类型的变量能够赋值给另一个 never 类型变量。

//在某些情况下使用 never 确实是符合逻辑的，比如一个只负责抛出错误的函数：
function justThrow(): never {
  throw new Error()
}


// 在类型流的分析中，一旦一个返回值类型为 never 的函数被调用，那么下方的代码都会被视为无效的代码（即无法执行到）：
function foo0(input: number) {
  if (input > 1) {
    justThrow();
    // 等同于 return 语句后的代码，即 Dead Code
    const name = 'linbaidu'
  }
}


// 假设，我们需要对一个联合类型的每个类型分支进行不同处理： (运行时会有报错，我们现在只是观察检查阶段的类型检查 ， 还没有进行值赋值，一旦赋值了下面的判断就相当于已经知道了)
declare var strOrNumOrBool: string | number | boolean;
//TODO:问问这个这么搞
// var strOrNumOrBool = 'str'
// 由于 TypeScript 强大的类型分析能力，每经过一个 if 语句处理，strOrNumOrBool 的类型分支就会减少一个（因为已经被对应的 typeof 处理过）。


// if (typeof strOrNumOrBool === "string") {
//   console.log("__str!");
// } else if (typeof strOrNumOrBool === "number") {
//   console.log("__num!");
// } else if (typeof strOrNumOrBool === "boolean") {
//   console.log("__bool!");
// } else {
//   throw new Error(`Unknown input type: ${strOrNumOrBool}`);
// }


/*假设某个粗心的同事新增了一个类型分支，strOrNumOrBool 变成了 strOrNumOrBoolOrFunc，却忘记新增对应的处理分支，此时在 else 代码块中就会出现将 Function 类型赋值给 never 类型变量的类型错误。这实际上就是利用了类型分析能力与 never 类型只能赋值给 never 类型这一点，来确保联合类型变量被妥善处理。 */
// if (typeof strOrNumOrBool === "string") {
//   // 一定是字符串！
//   strOrNumOrBool.charAt(1);
// } else if (typeof strOrNumOrBool === "number") {
//   strOrNumOrBool.toFixed();
// } else if (typeof strOrNumOrBool === "boolean") {
//   strOrNumOrBool === true;
// } else {
//   const _exhaustiveCheck: never = strOrNumOrBool;
//   throw new Error(`Unknown input type: ${_exhaustiveCheck}`);
// }

// # 主动使用 never 类型的两种方式，而 never 其实还会在某些情况下不请自来
// 这种情况仅会在你启用了 strictNullChecks 配置，同时禁用了 noImplicitAny 配置时才会出现。解决的办法也很简单，为这个数组声明一个具体类型即可。
const arr = [];
arr.push('123')

